#include "manager.h"
#include "tile.h"

using std::string;

Tile::Tile( int x, int y, string name, char symbol, bool passable ) : MapObject( x, y, name, symbol )
{
	layer = 0;
	this->passable = passable;
	this->itemContents.reserve( 10 );
	this->monsterContents.reserve( 5 );
	type_.tile = 1;
	visible = false;
	stairTo = -10;
	seen_ = false;
	state_ = state_floor;
}

Tile::~Tile()
{
	manager.getMTiles()[ x ][ y ] = nullptr;
}

bool Tile::move( int direction )
{
	return 0;
}

void Tile::draw()
{
	if( !visible )
	{
		if( !seen_ )
		{
			manager.mapaddch( y, x, ' ' );
			return;
		}
		manager.mapaddch( y, x, lastSymbol_ | lastColor_ );
		return;
	}
	seen_ = true;
	if( contents.empty() )
		manager.mapaddch( y, x, symbol | color );
	else
	{
		MapObject * mobj = *( contents.begin() );
		for( auto iter = contents.begin(); iter != contents.end(); iter++ )
			if( ( *iter )->layer >= mobj->layer )
				mobj = *iter;
		mobj->draw();
	}
	setDrawState();
}

void Tile::setDrawState()
{
	// mad
	lastColor_ = COLOR_GRAY;
	lastSymbol_ = symbol;
}

void Tile::convertToWall()
{
	symbol = '#';
	name = "wall";
	passable = false;
	stairTo = -10;
	state_ = state_wall;
}

void Tile::convertToFloor()
{
	symbol = '.';
	name = "floor";
	passable = true;
	stairTo = -10;
	state_ = state_floor;
}

void Tile::convertToStairs( int mapIndex )
{
	symbol = '>';
	stairTo = mapIndex;
	state_ = state_stair;
	passable = true;
}

void Tile::convertToDoor()
{
	name = "door";
	symbol = '+';
	color = COLOR_OYELLOW;
	open_ = false;
	passable = false;
	state_ = state_door;
}

bool Tile::open()
{
	if( state_ != state_door || open_ )
		return false;
	passable = true;
	symbol = '_';
	open_ = true;
	return true;
}

bool Tile::close()
{
	if( state_ != state_door || !open_ )
		return false;
	passable = false;
	symbol = '+';
	open_ = false;
	return true;
}

void Tile::hitEffect( int force )
{
	switch( state_ )
	{
	case state_door:
		if( force > 10 )
		{
			manager.addVisMsg( name + " is shot open!", this );
			convertToFloor();
		}
		break;
	default:
		if( force > 50 && !passable )
		{
			manager.addVisMsg( name + " is destroyed!", this );
			convertToFloor();
		}
		break;
	}
}

bool Tile::addToContents( MapObject * mobj )
{
	for( auto iter = contents.begin(); iter != contents.end(); iter++ )
		if( *iter == mobj )
			return false;
	contents.push_back( mobj );
	return true;
}

bool Tile::addToContents( Item * item )
{
	for( auto iter = itemContents.begin(); iter != itemContents.end(); iter++ )
		if( *iter == item )
			return false;
	itemContents.push_back( item );
	return true;
}

bool Tile::addToContents( Monster * mon )
{
	for( auto iter = monsterContents.begin();
		iter != monsterContents.end(); iter++ )
		if( *iter == mon )
			return false;
	monsterContents.push_back( mon );
	return true;
}

bool Tile::removeFromContents( MapObject * mobj )
{
	for( auto iter = contents.begin(); iter != contents.end(); iter++ )
		if( *iter == mobj )
		{
			contents.erase( iter );
			return true;
		}
	return false;
}

bool Tile::removeFromContents( Item * item )
{
	for( auto iter = itemContents.begin();
		iter != itemContents.end(); iter++ )
		if( *iter == item )
		{
			itemContents.erase( iter );
			return true;
		}
	return false;
}

bool Tile::removeFromContents( Monster * mon )
{
	for( auto iter = monsterContents.begin();
		iter != monsterContents.end(); iter++ )
		if( *iter == mon )
		{
			monsterContents.erase( iter );
			return true;
		}
	return false;
}

int Tile::setMapPos( map * m, int x, int y )
{
	if( this->x == x && this->y == y )
		return 0;
	m->mapTiles[ x ][ y ] = this;
	this->x = x;
	this->y = y;
	return 1;
}

void Tile::setTile( map * m, int x, int y, string name, char symbol, bool passable )
{
	setMapObject( m, x, y, name, symbol );
	this->passable = passable;
}

Tile::Tile()
{
	this->itemContents.reserve( 10 );
	this->monsterContents.reserve( 5 );
	type_.tile = 1;
	visible = false;
	stairTo = -10;
	seen_ = false;
	state_ = state_floor;
}